<template>
  <div class="fx-time-picker-scroll" ref="scrollDom" @scroll="handleScroll">
    <ul ref="scrollListDom" @mouseenter="scrollMouseenter" @mouseleave="scrollMouseleave">
      <li v-for="(item,index) in list" :key="item"
          :class="{active:currentIndex===index,disabled:disabled(index)}"
          @click="scrollClick(index)">
        {{ format(item) }}
      </li>
    </ul>
  </div>
</template>

<script lang="ts">
import { defineComponent, inject, onMounted, PropType, ref, SetupContext } from 'vue'
import { Emitter } from 'mitt'

interface ScrollProps {
  index: number;
  list: number[];
  timeType: 'hour' | 'min' | 'sec';
  min: string | number;
  max: string | number;
}

export default defineComponent({
  name: 'scroll',
  props: {
    index: {
      type: Number as PropType<number>,
      default: 0
    },
    list: {
      type: Array as PropType<number[]>,
      required: true
    },
    timeType: {
      type: String as PropType<'hour' | 'min' | 'sec'>,
      required: true
    },
    min: {
      type: [String, Number] as PropType<string | number>,
      default: -1
    },
    max: {
      type: [String, Number] as PropType<string | number>,
      default: -1
    }
  },
  setup (props: ScrollProps, ctx: SetupContext) {
    const timePickerMittEmit = inject<Emitter['emit']>('timePickerMittEmit')
    const scrollDom = ref<HTMLElement>()
    const scrollListDom = ref<HTMLElement>()
    const scrollIndex = ref<number>(0)
    const currentIndex = ref<number>(0)
    const oldPropsIndex = ref<number>(props.index)
    const format = (num: number): string => num < 10 ? `0${num}` : String(num)

    const disabled = (index: number) => {
      if (Number(props.min) >= 0) {
        return Number(props.min) > index
      }
      if (Number(props.max) >= 0) {
        return Number(props.max) < index
      }
    }

    // 发送当前滚动选中数据
    const sendScrollSelect = (index: number): void => {
      if (timePickerMittEmit) {
        timePickerMittEmit('scrollSelect', {
          index: index < 10 ? `0${index}` : String(index),
          timeType: props.timeType,
          type: ctx.attrs.time
        })
      }
    }

    // 点击选中
    const scrollClick = (index: number): void => {
      if (!scrollDom.value || !scrollListDom.value) return
      const min = Number(props.min)
      const max = Number(props.max)
      if (min >= 0 && index < min) index = min
      if (max >= 0 && index > max) index = max
      const childrenList = scrollListDom.value?.children
      if (childrenList[index]) {
        scrollDom.value.scrollTo(0, childrenList[index].clientHeight * index)
        currentIndex.value = index
        sendScrollSelect(index)
      }
    }

    // 滚轮进去
    const scrollMouseenter = (): void => {
      oldPropsIndex.value = props.index
      if (timePickerMittEmit) {
        timePickerMittEmit('scrollEnter', {
          timeType: props.timeType,
          type: ctx.attrs.time
        })
      }
    }

    const scrollMouseleave = (): void => {
      if (oldPropsIndex.value === props.index) {
        scrollClick(scrollIndex.value)
      } else {
        if (props.timeType === 'hour') {
          scrollClick(props.index < 24 ? props.index : 23)
        } else {
          scrollClick(props.index < 60 ? props.index : 59)
        }
      }
    }

    // 滚动判断对应选中值
    const handleScroll = (): void => {
      if (!scrollDom.value || !scrollListDom.value) return
      const childrenList = scrollListDom.value?.children
      const scrollTop = scrollDom.value.scrollTop
      const index = Math.floor(scrollTop / childrenList[0].clientHeight)
      scrollIndex.value = index
      currentIndex.value = index
      sendScrollSelect(scrollIndex.value)
    }

    onMounted(() => {
      scrollClick(props.index || 0)
    })

    return {
      scrollDom,
      scrollIndex,
      currentIndex,
      scrollListDom,
      disabled,
      format,
      scrollClick,
      scrollMouseenter,
      scrollMouseleave,
      handleScroll
    }
  }
})
</script>
